<?php

namespace App\Services;

use Illuminate\Support\Facades\File;
use Illuminate\Support\Str;

class EnvConfigService
{
    protected $envPath;

    public function __construct()
    {
        $this->envPath = base_path('.env');
    }

    /**
     * 读取 .env 文件内容
     *
     * @return array
     */
    public function readEnv(): array
    {
        if (!File::exists($this->envPath)) {
            return [];
        }

        $content = File::get($this->envPath);
        $lines = explode("\n", $content);
        $config = [];

        foreach ($lines as $line) {
            $line = trim($line);
            
            // 跳过空行和注释
            if (empty($line) || Str::startsWith($line, '#')) {
                continue;
            }

            // 解析 KEY=VALUE 格式
            if (strpos($line, '=') !== false) {
                [$key, $value] = explode('=', $line, 2);
                $key = trim($key);
                $value = trim($value);
                
                // 移除引号
                if (
                    (Str::startsWith($value, '"') && Str::endsWith($value, '"')) ||
                    (Str::startsWith($value, "'") && Str::endsWith($value, "'"))
                ) {
                    $value = substr($value, 1, -1);
                }
                
                $config[$key] = $value;
            }
        }

        return $config;
    }

    /**
     * 更新 .env 文件中的配置项
     *
     * @param array $updates 要更新的配置项 [key => value]
     * @return bool
     */
    public function updateEnv(array $updates): bool
    {
        if (!File::exists($this->envPath)) {
            return false;
        }

        $content = File::get($this->envPath);
        $lines = explode("\n", $content);
        $updated = false;
        $foundKeys = [];

        // 第一遍：更新已存在的配置项
        foreach ($lines as $index => $line) {
            $originalLine = $line;
            $trimmedLine = trim($line);
            
            // 跳过空行和注释
            if (empty($trimmedLine) || Str::startsWith($trimmedLine, '#')) {
                continue;
            }

            // 解析 KEY=VALUE 格式
            if (strpos($trimmedLine, '=') !== false) {
                [$key, $value] = explode('=', $trimmedLine, 2);
                $key = trim($key);
                
                // 如果是要更新的键，则更新值
                if (isset($updates[$key])) {
                    $newValue = $this->formatEnvValue($updates[$key]);
                    // 保持原有的缩进和格式
                    $indent = '';
                    if (preg_match('/^(\s+)/', $originalLine, $matches)) {
                        $indent = $matches[1];
                    }
                    $lines[$index] = $indent . "{$key}={$newValue}";
                    $foundKeys[] = $key;
                    unset($updates[$key]);
                    $updated = true;
                }
            }
        }

        // 第二遍：添加新的配置项（如果存在）
        if (!empty($updates)) {
            // 在文件末尾添加新配置项
            // 先添加一个空行（如果最后一行不是空行）
            $lastLine = end($lines);
            if (!empty(trim($lastLine))) {
                $lines[] = '';
            }
            
            // 根据配置键的前缀判断应该添加的注释分组
            $groupComments = [
                'APP_' => '# Application Configuration',
                'DB_' => '# Database Configuration',
                'REDIS_' => '# Redis Configuration',
                'JWT_' => '# JWT Configuration',
                'WEBSOCKET_' => '# WebSocket Configuration',
                'MAIL_' => '# Mail Configuration',
                'CACHE_' => '# Cache Configuration',
                'SESSION_' => '# Session Configuration',
                'QUEUE_' => '# Queue Configuration',
            ];
            
            // 检查是否需要添加分组注释
            $addedComments = [];
            foreach ($updates as $key => $value) {
                foreach ($groupComments as $prefix => $comment) {
                    if (strpos($key, $prefix) === 0 && !in_array($comment, $addedComments)) {
                        // 检查文件中是否已有该注释
                        $hasComment = false;
                        foreach ($lines as $line) {
                            if (strpos($line, $comment) !== false) {
                                $hasComment = true;
                                break;
                            }
                        }
                        if (!$hasComment) {
                            $lines[] = $comment;
                            $addedComments[] = $comment;
                        }
                        break;
                    }
                }
            }
            
            // 如果没有匹配的分组注释，添加通用注释
            if (empty($addedComments)) {
                $lines[] = '# Custom Configuration';
            }
            
            // 添加新配置项
            foreach ($updates as $key => $value) {
                $newValue = $this->formatEnvValue($value);
                $lines[] = "{$key}={$newValue}";
                $updated = true;
            }
        }

        if ($updated) {
            // 确保文件以换行符结尾
            $content = implode("\n", $lines);
            if (!Str::endsWith($content, "\n")) {
                $content .= "\n";
            }
            File::put($this->envPath, $content);
        }

        return $updated;
    }

    /**
     * 格式化环境变量值
     *
     * @param mixed $value
     * @return string
     */
    protected function formatEnvValue($value): string
    {
        // 如果是布尔值，转换为字符串
        if (is_bool($value)) {
            return $value ? 'true' : 'false';
        }

        // 如果是数字字符串，直接返回（不需要引号）
        if (is_numeric($value)) {
            return (string) $value;
        }

        $value = (string) $value;

        // 空值
        if (empty($value)) {
            return '""';
        }

        // URL 地址通常不需要引号（除非包含特殊字符）
        if (
            (strpos($value, 'http://') === 0 || strpos($value, 'https://') === 0 || 
             strpos($value, 'ws://') === 0 || strpos($value, 'wss://') === 0) &&
            strpos($value, ' ') === false &&
            strpos($value, '#') === false
        ) {
            return $value;
        }

        // 如果值包含空格、特殊字符，需要加引号
        if (
            strpos($value, ' ') !== false ||
            strpos($value, '#') !== false ||
            strpos($value, '=') !== false ||
            strpos($value, "\n") !== false ||
            strpos($value, '$') !== false
        ) {
            // 转义双引号和反斜杠
            $value = str_replace('\\', '\\\\', $value);
            $value = str_replace('"', '\"', $value);
            return '"' . $value . '"';
        }

        return $value;
    }

    /**
     * 获取 WebSocket 相关配置
     *
     * @return array
     */
    public function getWebSocketConfig(): array
    {
        $env = $this->readEnv();
        
        return [
            'WEBSOCKET_ENABLED' => $env['WEBSOCKET_ENABLED'] ?? 'false',
            'WEBSOCKET_BASE_URL' => $env['WEBSOCKET_BASE_URL'] ?? 'http://localhost:8080',
            'WEBSOCKET_WS_URL' => $env['WEBSOCKET_WS_URL'] ?? 'ws://localhost:8080',
            'WEBSOCKET_TIMEOUT' => $env['WEBSOCKET_TIMEOUT'] ?? '5',
        ];
    }

    /**
     * 更新 WebSocket 配置
     *
     * @param array $config
     * @return bool
     */
    public function updateWebSocketConfig(array $config): bool
    {
        $updates = [];
        
        if (isset($config['WEBSOCKET_ENABLED'])) {
            $updates['WEBSOCKET_ENABLED'] = $config['WEBSOCKET_ENABLED'] === true || $config['WEBSOCKET_ENABLED'] === 'true' || $config['WEBSOCKET_ENABLED'] === '1' ? 'true' : 'false';
        }
        
        if (isset($config['WEBSOCKET_BASE_URL'])) {
            $updates['WEBSOCKET_BASE_URL'] = $config['WEBSOCKET_BASE_URL'];
        }
        
        if (isset($config['WEBSOCKET_WS_URL'])) {
            $updates['WEBSOCKET_WS_URL'] = $config['WEBSOCKET_WS_URL'];
        }
        
        if (isset($config['WEBSOCKET_TIMEOUT'])) {
            $updates['WEBSOCKET_TIMEOUT'] = (string) $config['WEBSOCKET_TIMEOUT'];
        }

        return $this->updateEnv($updates);
    }

    /**
     * 删除环境变量
     *
     * @param array $keys 要删除的键数组
     * @return bool
     */
    public function deleteEnv(array $keys): bool
    {
        if (!File::exists($this->envPath)) {
            return false;
        }

        $content = File::get($this->envPath);
        $lines = explode("\n", $content);
        $updated = false;
        $keysToDelete = array_flip($keys);

        foreach ($lines as $index => $line) {
            $trimmedLine = trim($line);
            
            // 跳过空行和注释
            if (empty($trimmedLine) || Str::startsWith($trimmedLine, '#')) {
                continue;
            }

            // 解析 KEY=VALUE 格式
            if (strpos($trimmedLine, '=') !== false) {
                [$key, $value] = explode('=', $trimmedLine, 2);
                $key = trim($key);
                
                // 如果是要删除的键，则删除该行
                if (isset($keysToDelete[$key])) {
                    unset($lines[$index]);
                    $updated = true;
                }
            }
        }

        if ($updated) {
            // 重新索引数组
            $lines = array_values($lines);
            // 确保文件以换行符结尾
            $content = implode("\n", $lines);
            if (!Str::endsWith($content, "\n")) {
                $content .= "\n";
            }
            File::put($this->envPath, $content);
        }

        return $updated;
    }

    /**
     * 获取所有环境变量（按分组）
     *
     * @return array
     */
    public function getAllEnvGrouped(): array
    {
        $env = $this->readEnv();
        
        $groups = [
            'app' => [
                'title' => '应用配置',
                'keys' => ['APP_NAME', 'APP_ENV', 'APP_KEY', 'APP_DEBUG', 'APP_URL', 'APP_TIMEZONE'],
            ],
            'database' => [
                'title' => '数据库配置',
                'keys' => ['DB_CONNECTION', 'DB_HOST', 'DB_PORT', 'DB_DATABASE', 'DB_USERNAME', 'DB_PASSWORD', 'DB_CHARSET', 'DB_COLLATION'],
            ],
            'redis' => [
                'title' => 'Redis配置',
                'keys' => ['REDIS_HOST', 'REDIS_PASSWORD', 'REDIS_PORT', 'REDIS_DB', 'REDIS_CLIENT'],
            ],
            'jwt' => [
                'title' => 'JWT配置',
                'keys' => ['JWT_SECRET', 'JWT_TTL', 'JWT_REFRESH_TTL', 'JWT_ALGO'],
            ],
            'websocket' => [
                'title' => 'WebSocket配置',
                'keys' => ['WEBSOCKET_ENABLED', 'WEBSOCKET_BASE_URL', 'WEBSOCKET_WS_URL', 'WEBSOCKET_TIMEOUT'],
            ],
            'mail' => [
                'title' => '邮件配置',
                'keys' => ['MAIL_MAILER', 'MAIL_HOST', 'MAIL_PORT', 'MAIL_USERNAME', 'MAIL_PASSWORD', 'MAIL_ENCRYPTION', 'MAIL_FROM_ADDRESS', 'MAIL_FROM_NAME'],
            ],
            'cache' => [
                'title' => '缓存配置',
                'keys' => ['CACHE_DRIVER', 'CACHE_PREFIX'],
            ],
            'session' => [
                'title' => 'Session配置',
                'keys' => ['SESSION_DRIVER', 'SESSION_LIFETIME'],
            ],
            'queue' => [
                'title' => '队列配置',
                'keys' => ['QUEUE_CONNECTION', 'QUEUE_DRIVER'],
            ],
            'other' => [
                'title' => '其他配置',
                'keys' => [],
            ],
        ];

        $result = [];
        $allGroupedKeys = [];

        // 收集所有分组的键
        foreach ($groups as $groupKey => $group) {
            $allGroupedKeys = array_merge($allGroupedKeys, $group['keys']);
        }

        // 处理分组
        foreach ($groups as $groupKey => $group) {
            $items = [];
            foreach ($group['keys'] as $key) {
                if (isset($env[$key])) {
                    $items[] = [
                        'key' => $key,
                        'value' => $env[$key],
                    ];
                }
            }
            $result[$groupKey] = [
                'title' => $group['title'],
                'items' => $items,
            ];
        }

        // 处理其他未分组的配置
        foreach ($env as $key => $value) {
            if (!in_array($key, $allGroupedKeys)) {
                $result['other']['items'][] = [
                    'key' => $key,
                    'value' => $value,
                ];
            }
        }

        // 移除空的分组
        foreach ($result as $groupKey => $group) {
            if (empty($group['items'])) {
                unset($result[$groupKey]);
            }
        }

        return $result;
    }

    /**
     * 批量更新环境变量
     *
     * @param array $configs 配置项数组 [['key' => 'KEY', 'value' => 'value'], ...]
     * @return bool
     */
    public function batchUpdateEnv(array $configs): bool
    {
        $updates = [];
        foreach ($configs as $config) {
            if (isset($config['key']) && isset($config['value'])) {
                $updates[$config['key']] = $config['value'];
            }
        }

        return $this->updateEnv($updates);
    }
}

